#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File    : /decorator_func.py
@Time    : 2021-03-16 22:06:19
@Author  : Gray Snail
@Version : 1.0
@Contact : shtao2011@sina.com
@License : Copyright (c) 2021 Gray Snail
@Desc    : None
'''


'''
函数装饰器，不带参数（2层）和带参数（3层）
'''

from functools import wraps
from datetime import datetime


def log(func):
    @wraps(func)
    def inner(*args, **kwargs):
        print(func.__name__)
        print('before running...')
        return func(*args, **kwargs)

    return inner


@log
def test_decorator():
    print('normal func')


# 以上等价于
# test_decorator = log(test_decorator)


def runtime(start_time, end_time):
    def decorator(func):
        @wraps(func)
        def inner(*args, **kwargs):
            s = datetime.now()
            res = func(*args, **kwargs)
            e = datetime.now()
            print(start_time, end_time)
            print('time：{}'.format((e - s).total_seconds()))
            return res

        return inner

    return decorator


@runtime(1, 100)
def run():
    res = 0
    for i in range(10000):
        res += i
    print(res)


# 等价表示
# run = runtime(1, 10)(run)


# 作用于类的装饰器
# 其返回必然是class，但可以对原class做增强


def deco_class(cls):
    class Wrap:
        def __init__(self, *args, **kwargs):
            self.wrapper = cls(*args, **kwargs)

        def __getattr__(self, name):
            print('get arrt:', name)
            return getattr(self.wrapper, name)

    return Wrap


@deco_class
class Foo(object):
    def __init__(self, name):
        self.name = name

    def show(self):
        print(self.name)


'''
等价关系

Foo = deco_class(Foo)

要接受参数也是在上边包装一层参数
'''


def test_decorator_cls():
    foo = Foo('Anna')
    foo.show()


if __name__ == '__main__':
    test_decorator()

    run()

    test_decorator_cls()
